package cn.hashq.netpoststation.service.impl;

import cn.hashq.netpoststation.cache.ChannelCache;
import cn.hashq.netpoststation.dto.AddPortMapDTO;
import cn.hashq.netpoststation.entity.PortMap;
import cn.hashq.netpoststation.mapper.PortMapMapper;
import cn.hashq.netpoststation.service.PortMapManagerService;
import cn.hashq.netpoststation.util.NettyUtil;
import cn.hashq.netpoststation.vo.ServerResponse;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.netty.channel.Channel;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class PortMapManagerServiceImpl extends ServiceImpl<PortMapMapper, PortMap> implements PortMapManagerService {

    @Resource
    private NettyUtil nettyUtil;

    @Override
    public ServerResponse addPortMap(AddPortMapDTO portMapDTO) {
        PortMap portMap = new PortMap();
        BeanUtils.copyProperties(portMapDTO, portMap);
        portMap.setStatus(1);
        nettyUtil.startPortMap(portMap);
        save(portMap);
        return ServerResponse.createSuccessResult();
    }

    @Override
    public ServerResponse listPortMap() {
        return ServerResponse.createSuccessResult(list());
    }

    @Override
    public ServerResponse removePortMap(Long id) {
        if (Objects.isNull(id)) {
            return ServerResponse.createFailedResult("参数不能为空");
        }
        PortMap portMap = getById(id);
        if (Objects.isNull(portMap)) {
            return ServerResponse.createFailedResult("该数据不存在");
        }
        closeChannelByPort(portMap.getServerPort());
        removeById(id);
        return ServerResponse.createSuccessResult();
    }

    @Override
    public ServerResponse notifyPortMapStatus(Long id) {
        if (Objects.isNull(id)) {
            return ServerResponse.createFailedResult("参数不能为空");
        }
        PortMap portMap = getById(id);
        if (portMap.getStatus().compareTo(1) == 0) {
            closeChannelByPort(portMap.getServerPort());
            portMap.setStatus(0);
        } else {
            portMap.setStatus(1);
            nettyUtil.startPortMap(portMap);
        }
        updateById(portMap);
        return ServerResponse.createSuccessResult();
    }

    private void closeChannelByPort(Integer port) {
        List<Channel> channels = ChannelCache.getInstance().getMap().values()
                .stream().filter(e -> {
                    SocketAddress socketAddress = e.localAddress();
                    if (socketAddress instanceof InetSocketAddress) {
                        return port.compareTo(((InetSocketAddress) socketAddress).getPort()) == 0;
                    }
                    return false;
                }).collect(Collectors.toList());
        for (Channel channel : channels) {
            channel.close();
            ChannelCache.getInstance().removeChannel(channel.id().asLongText());
        }
    }

}
